home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 12 / Example 12.2 / effect.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-01  |  10.7 KB  |  341 lines

  1. #include "effect.h"
  2.  
  3. //Global Effect variables
  4. ID3DXMesh *billboardMesh = NULL;
  5. D3DMATERIAL9 whiteMtrl;
  6. SHADER effectVertexShader, effectPixelShader;
  7. D3DXHANDLE effectMatW, effectMatVP, effectVCol;
  8.  
  9. //Global Effect Textures
  10. IDirect3DTexture9* runesTexture = NULL;
  11. IDirect3DTexture9* cloudTexture = NULL;
  12. IDirect3DTexture9* fireballTexture = NULL;
  13.  
  14. struct SimpleVertex
  15. {
  16.     SimpleVertex(){}
  17.     SimpleVertex(D3DXVECTOR3 pos, D3DXVECTOR3 norm, D3DXVECTOR2 _uv)
  18.     {
  19.         position = pos;
  20.         normal = norm;
  21.         uv = _uv;
  22.     }
  23.  
  24.     D3DXVECTOR3 position, normal;
  25.     D3DXVECTOR2 uv;
  26.  
  27.     static const DWORD FVF;
  28. };
  29.  
  30. const DWORD SimpleVertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
  31.  
  32. void LoadEffectResources(IDirect3DDevice9 *m_pDevice)
  33. {
  34.     //Calculate sight mesh (a simple quad)
  35.     D3DXCreateMeshFVF(2, 4, D3DXMESH_MANAGED, SimpleVertex::FVF, m_pDevice, &billboardMesh);
  36.  
  37.     //Create 4 vertices
  38.     SimpleVertex* v = 0;
  39.     billboardMesh->LockVertexBuffer(0,(void**)&v);
  40.     v[0] = SimpleVertex(D3DXVECTOR3(-0.5f, 0.0f, 0.5f), D3DXVECTOR3(0.0f, 1.0f, 0.0f), D3DXVECTOR2(0, 0));
  41.     v[1] = SimpleVertex(D3DXVECTOR3( 0.5f, 0.0f, 0.5f), D3DXVECTOR3(0.0f, 1.0f, 0.0f), D3DXVECTOR2(1, 0));
  42.     v[2] = SimpleVertex(D3DXVECTOR3(-0.5f, 0.0f, -0.5f),D3DXVECTOR3(0.0f, 1.0f, 0.0f), D3DXVECTOR2(0, 1));
  43.     v[3] = SimpleVertex(D3DXVECTOR3( 0.5f, 0.0f, -0.5f),D3DXVECTOR3(0.0f, 1.0f, 0.0f), D3DXVECTOR2(1, 1));
  44.     billboardMesh->UnlockVertexBuffer();
  45.  
  46.     //Create 2 faces
  47.     WORD* indices = 0;
  48.     billboardMesh->LockIndexBuffer(0,(void**)&indices);    
  49.     indices[0] = 0; indices[1] = 1; indices[2] = 2;
  50.     indices[3] = 1; indices[4] = 3; indices[5] = 2;
  51.     billboardMesh->UnlockIndexBuffer();
  52.  
  53.     //Set Attributes for the 2 faces
  54.     DWORD *att = 0;
  55.     billboardMesh->LockAttributeBuffer(0,&att);
  56.     att[0] = 0; att[1] = 0;
  57.     billboardMesh->UnlockAttributeBuffer();
  58.  
  59.     //Sight MTRL
  60.     memset(&whiteMtrl, 0, sizeof(D3DMATERIAL9));
  61.     whiteMtrl.Diffuse = whiteMtrl.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
  62.  
  63.     //Load Shaders
  64.     effectVertexShader.Init(m_pDevice, "shaders/effect.vs", VERTEX_SHADER);
  65.     effectPixelShader.Init(m_pDevice, "shaders/effect.ps", PIXEL_SHADER);
  66.  
  67.     //Get constants
  68.     effectMatW = effectVertexShader.GetConstant("matW");
  69.     effectMatVP = effectVertexShader.GetConstant("matVP");
  70.     effectVCol = effectVertexShader.GetConstant("vertexColor");
  71.  
  72.     //Load textures
  73.     D3DXCreateTextureFromFile(m_pDevice, "textures/runes.dds", &runesTexture);
  74.     D3DXCreateTextureFromFile(m_pDevice, "textures/cloud.dds", &cloudTexture);
  75.     D3DXCreateTextureFromFile(m_pDevice, "textures/fireball.dds", &fireballTexture);
  76. }
  77.  
  78. void UnloadEffectResources()
  79. {
  80.     if(billboardMesh)billboardMesh->Release();
  81.     billboardMesh = NULL;
  82. }
  83.  
  84. //////////////////////////////////////////////////////////////////////////////////////////////
  85. //                                TRANSFORM                                                    //
  86. //////////////////////////////////////////////////////////////////////////////////////////////
  87.  
  88. TRANSFORM::TRANSFORM(){ m_pos = m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f); m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f); }
  89. TRANSFORM::TRANSFORM(D3DXVECTOR3 _pos){ m_pos = _pos; m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f); m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f); }
  90. TRANSFORM::TRANSFORM(D3DXVECTOR3 _pos, D3DXVECTOR3 _rot){ m_pos = _pos; m_rot = _rot; m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f); }
  91. TRANSFORM::TRANSFORM(D3DXVECTOR3 _pos, D3DXVECTOR3 _rot, D3DXVECTOR3 _sca){ m_pos = _pos; m_rot = _rot; m_sca = _sca; }
  92.  
  93. void TRANSFORM::Init(D3DXVECTOR3 _pos){ m_pos = _pos; m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f); m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f); }
  94. void TRANSFORM::Init(D3DXVECTOR3 _pos, D3DXVECTOR3 _rot){ m_pos = _pos; m_rot = _rot; m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f); }
  95. void TRANSFORM::Init(D3DXVECTOR3 _pos, D3DXVECTOR3 _rot, D3DXVECTOR3 _sca){ m_pos = _pos; m_rot = _rot; m_sca = _sca; }
  96.  
  97. D3DXMATRIX TRANSFORM::GetWorldMatrix()
  98. {
  99.     D3DXMATRIX p, r, s;
  100.     D3DXMatrixTranslation(&p, m_pos.x, m_pos.y, m_pos.z);
  101.     D3DXMatrixRotationYawPitchRoll(&r, m_rot.y, m_rot.x, m_rot.z);
  102.     D3DXMatrixScaling(&s, m_sca.x, m_sca.y, m_sca.z);
  103.     D3DXMATRIX world = s * r * p;
  104.     return world;
  105. }
  106.  
  107. //////////////////////////////////////////////////////////////////////////////////////////////
  108. //                                EFFECTS    BASE CLASS                                            //
  109. //////////////////////////////////////////////////////////////////////////////////////////////
  110.  
  111. EFFECT::EFFECT(IDirect3DDevice9 *Dev)
  112. {
  113.     m_pDevice = Dev;
  114.     m_time = 0.0f;
  115.     m_color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);    //White
  116. }
  117.  
  118. void EFFECT::PreRender()
  119. {
  120.     //Enable alpha blending
  121.     m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  122.     m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  123.     m_pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  124.     m_pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  125.     m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
  126.     m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  127.     m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
  128.     m_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  129.     m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, false);
  130.     m_pDevice->SetRenderState(D3DRS_LIGHTING, false);
  131.  
  132.     //Set vertex shader variables
  133.     D3DXMATRIX view, proj;
  134.     m_pDevice->GetTransform(D3DTS_VIEW, &view);
  135.     m_pDevice->GetTransform(D3DTS_PROJECTION, &proj);
  136.     
  137.     effectVertexShader.SetMatrix(effectMatVP, view * proj);
  138.     effectVertexShader.SetVector4(effectVCol, m_color);
  139.  
  140.     //Set material
  141.     m_pDevice->SetMaterial(&whiteMtrl);
  142.  
  143.     //enable Shaders
  144.     effectVertexShader.Begin();
  145.     effectPixelShader.Begin();
  146. }
  147.  
  148. void EFFECT::PostRender()
  149. {
  150.     //Reset renderstates
  151.     m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
  152.     m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);
  153.     m_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
  154.  
  155.     //Disable shaders
  156.     effectVertexShader.End();
  157.     effectPixelShader.End();
  158. }
  159.  
  160. //////////////////////////////////////////////////////////////////////////////////////////////
  161. //                                EFFECTS    SPELL                                                //
  162. //////////////////////////////////////////////////////////////////////////////////////////////
  163.  
  164. EFFECT_SPELL::EFFECT_SPELL(IDirect3DDevice9 *Dev, D3DXVECTOR3 _pos) : EFFECT(Dev), m_t1(_pos, D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(0.1f, 0.1f, 0.1f))
  165. {
  166.     m_t1.m_pos.y += 1.0f;
  167.     m_color = D3DXVECTOR4(rand()%1000 / 1000.0f, rand()%1000 / 1000.0f, rand()%1000 / 1000.0f, 0.0f);
  168.  
  169.     for(int i=0;i<10;i++)
  170.     {
  171.         float angle = i * (D3DX_PI / 5.0f);
  172.             
  173.         m_c[i].Init(_pos + D3DXVECTOR3(cos(angle) * 0.5f, 2.5f, sin(angle) * 0.5f),
  174.                   D3DXVECTOR3(D3DX_PI * 0.5f, angle, 0.0f),
  175.                   D3DXVECTOR3(4.0f, 4.0f, 6.0f));
  176.     }
  177. }
  178.  
  179. void EFFECT_SPELL::Update(float timeDelta)
  180. {
  181.     m_time += timeDelta;
  182.  
  183.     //Update Lower spinning quad...
  184.     m_t1.m_rot.y += timeDelta;
  185.  
  186.     //Update cloud
  187.     for(int i=0;i<10;i++)
  188.         m_c[i].m_rot.y -= timeDelta;
  189.  
  190.     //Update Spinning quad scale
  191.     if(m_time < 1.5f)m_t1.m_sca += D3DXVECTOR3(timeDelta, timeDelta, timeDelta) * 4.0f;
  192.     if(m_time > 4.5f)m_t1.m_sca -= D3DXVECTOR3(timeDelta, timeDelta, timeDelta) * 4.0f;
  193.  
  194.     //Calculate alpha
  195.     m_color.w = m_t1.m_sca.x / 6.0f;
  196. }
  197.  
  198. void EFFECT_SPELL::Render()
  199. {
  200.     PreRender();
  201.  
  202.     if(billboardMesh)
  203.     {
  204.         //Spinning quad
  205.         m_pDevice->SetTexture(0, runesTexture);
  206.         effectVertexShader.SetMatrix(effectMatW, m_t1.GetWorldMatrix());
  207.         billboardMesh->DrawSubset(0);
  208.  
  209.         //Cloud
  210.         m_pDevice->SetTexture(0, cloudTexture);
  211.         for(int i=0;i<10;i++)
  212.         {
  213.             effectVertexShader.SetMatrix(effectMatW, m_c[i].GetWorldMatrix());
  214.             billboardMesh->DrawSubset(0);
  215.         }
  216.     }
  217.  
  218.     PostRender();
  219. }
  220.  
  221. bool EFFECT_SPELL::isDead()
  222. {
  223.     return m_t1.m_sca.x < 0.0f;
  224. }
  225.  
  226. //////////////////////////////////////////////////////////////////////////////////////////////
  227. //                                EFFECTS    FIREBALL                                            //
  228. //////////////////////////////////////////////////////////////////////////////////////////////
  229.  
  230. EFFECT_FIREBALL::EFFECT_FIREBALL(IDirect3DDevice9 *Dev, BONE *_src, D3DXVECTOR3 _dest) : EFFECT(Dev)
  231. {
  232.     m_pSrcBone = _src;
  233.     m_dest = _dest;
  234.     m_color.w = 0.01f;
  235.     m_prc = 0.0f;
  236.     m_speed = 22.0f;
  237.  
  238.     if(m_pSrcBone != NULL)
  239.     {
  240.         D3DXMATRIX mat = m_pSrcBone->CombinedTransformationMatrix;        
  241.         m_t1.Init(D3DXVECTOR3(mat(3,0), mat(3, 1), mat(3, 2)), D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(0.1f, 0.1f, 0.1f));
  242.     }
  243. }
  244.  
  245. void EFFECT_FIREBALL::Update(float timeDelta)
  246. {
  247.     m_t1.m_rot += D3DXVECTOR3(0.5f, 0.5f, 0.5f) * timeDelta;
  248.  
  249.     if(m_time < 1.0f && m_pSrcBone != NULL)        //Follow staff (Phase 1)
  250.     {
  251.         m_time += timeDelta;
  252.         D3DXMATRIX mat = m_pSrcBone->CombinedTransformationMatrix;
  253.  
  254.         //Extract position from staff bone
  255.         m_t1.m_pos = D3DXVECTOR3(mat(3,0), mat(3, 1), mat(3, 2));
  256.         m_t1.m_sca = D3DXVECTOR3(1.5f, 1.5f, 1.5f) * m_time;
  257.  
  258.         //Fade in fireball (w = alpha)
  259.         m_color.w = m_time;
  260.  
  261.         if(m_time > 1.0f)
  262.         {
  263.             m_color.w = m_time * 0.5f;
  264.             m_origin = m_t1.m_pos;
  265.             m_length = D3DXVec3Length(&(m_origin - m_dest));
  266.         }
  267.     }
  268.     else if(m_prc < 1.0f)        //Fly towards target (Phase 2)
  269.     {
  270.         m_prc += (m_speed * timeDelta) / m_length;
  271.         m_t1.m_pos = GetPosition(m_prc);
  272.     }
  273.     else                    //Explode    (Phase 3)
  274.     {
  275.         m_prc += (m_speed * timeDelta) / m_length;
  276.         m_t1.m_sca += D3DXVECTOR3(5.0f, 5.0f, 5.0f) * timeDelta;
  277.         m_color.w -= timeDelta * 0.5f;
  278.     }
  279. }
  280.  
  281. void EFFECT_FIREBALL::Render()
  282. {
  283.     PreRender();
  284.  
  285.     if(billboardMesh)
  286.     {
  287.         //Create a Trail of small fireballs...
  288.         D3DXVECTOR3 orgRot = m_t1.m_rot;
  289.         D3DXVECTOR3 rotations[] = {D3DXVECTOR3(0.0f, 0.0f, 0.0f),
  290.                                    D3DXVECTOR3(D3DX_PI * 0.5f, 0.0f, 0.0f),
  291.                                    D3DXVECTOR3(0.0f, D3DX_PI * 0.5f, 0.0f),
  292.                                    D3DXVECTOR3(0.0f, 0.0f, D3DX_PI * 0.5f)};
  293.  
  294.         D3DXVECTOR3 orgPos = m_t1.m_pos;
  295.         D3DXVECTOR3 positions[] = {m_t1.m_pos, 
  296.                                    GetPosition(m_prc - (1.5f / m_length)),
  297.                                    GetPosition(m_prc - (2.5f / m_length)),
  298.                                    GetPosition(m_prc - (3.25f / m_length)),
  299.                                    GetPosition(m_prc - (4.0f / m_length))};
  300.  
  301.         D3DXVECTOR3 orgSca = m_t1.m_sca;
  302.         D3DXVECTOR3 scales[] = {m_t1.m_sca, 
  303.                                 m_t1.m_sca * 0.8f,
  304.                                 m_t1.m_sca * 0.6f,
  305.                                 m_t1.m_sca * 0.4f,
  306.                                 m_t1.m_sca * 0.2f};
  307.     
  308.         m_pDevice->SetTexture(0, fireballTexture);
  309.         for(int t=0;t<5;t++)
  310.             for(int i=0;i<4;i++)
  311.             {
  312.                 m_t1.m_pos = positions[t];
  313.                 m_t1.m_rot = orgRot + rotations[i];
  314.                 m_t1.m_sca = scales[t];
  315.  
  316.                 effectVertexShader.SetMatrix(effectMatW, m_t1.GetWorldMatrix());
  317.                 billboardMesh->DrawSubset(0);
  318.             }
  319.  
  320.         m_t1.m_pos = orgPos;
  321.         m_t1.m_rot = orgRot;
  322.         m_t1.m_sca = orgSca;
  323.     }
  324.  
  325.     PostRender();
  326. }
  327.  
  328. bool EFFECT_FIREBALL::isDead()
  329. {
  330.     return m_pSrcBone == NULL || m_color.w < 0.0f;
  331. }
  332.  
  333. D3DXVECTOR3 EFFECT_FIREBALL::GetPosition(float p)
  334. {
  335.     if(p < 0.0f)p = 0.0f;
  336.     if(p > 1.0f)p = 1.0f;
  337.  
  338.     D3DXVECTOR3 pos = m_origin * (1.0f - p) + m_dest * p;    //Lerp between m_origin and dest
  339.     pos.y += sin(p * D3DX_PI) * 3.0f;                        //Add Arc
  340.     return pos;
  341. }